<?php

namespace Weixin;

abstract class WechatCallbackApi extends \Home {

	private $token;
	private $post;
	private $params;
	private $myUserName;
	private $userName;

	public function __construct() {
		$this->token = \Config\Main::WEIXIN_TOKEN;
		$this->post = file_get_contents("php://input");
		$this->valid();
		$this->setGetMessage();
		$this->log($this->params);
		$this->responseMessage();
	}

	public static function getWeixinAccessToken() {
		$redis = \Lib\Db\Redis::instance();
		$appId = \Config\Main::WEIXIN_APPID;
		$secret = \Config\Main::WEIXIN_APPSECRET;
		$key = 'WEIXIN_ACCESS_TOKEN_' . $appId;
		$accessToken = $redis->get($key);
		if ($accessToken) {
			return $accessToken;
		}
		$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appId . '&secret=' . $secret;
		$result = file_get_contents($url);
		$data = json_decode($result, true);
		$accessToken = $data['access_token'];
		$expires = $data['expires_in'];
		$expires = $expires - 20;
		if ($expires < 0) {
			$expires = 0;
		}
		$redis->setex($key, $expires, $accessToken);
		return $accessToken;
	}

	abstract protected function processEvent($param);

	protected function responseMessage() {
		if (!$this->params) {
			return;
		}
		$msgType = $this->params['MsgType'];
		$this->myUserName = $this->params['ToUserName'];
		$this->userName = $this->params['FromUserName'];

		switch ($msgType) {
			case 'event':
				$this->processEvent($this->params);
				break;
		}
	}

	protected function showText($content) {
		echo $this->callMessage($this->userName, $content);
	}

	protected function showImageText($content) {
		echo $this->callImageTextMessage($this->userName, $content);
	}

	private function callMessage($userName, $content) {
		$time = time();
		$str = "<xml><ToUserName><![CDATA[{$userName}]]></ToUserName><FromUserName><![CDATA[{$this->params['ToUserName']}]]></FromUserName><CreateTime>{$time}</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{$content}]]></Content></xml>
";
		return $str;
	}

	private function callImageTextMessage($userName, $content) {
		$time = time();
		$str = '<xml>';
		$str .= '<ToUserName><![CDATA[' . $userName . ']]></ToUserName>';
		$str .= '<FromUserName><![CDATA[' . $this->params['ToUserName'] . ']]></FromUserName>';
		$str .= '<CreateTime>' . $time . '</CreateTime>';
		$str .= '<MsgType><![CDATA[news]]></MsgType>';
		$str .= '<ArticleCount>' . count($content) . '</ArticleCount>';
		$str .= '<Articles>';
		foreach ($content as $val) {
			$str .= '<item>';
			$str .= '<Title><![CDATA[' . $val['title'] . ']]></Title>';
			$str .= '<Description><![CDATA[' . $val['description1'] . ']]></Description>';
			$str .= '<PicUrl><![CDATA[' . $val['picurl'] . ']]></PicUrl>';
			$str .= '<Url><![CDATA[' . $val['url'] . ']]></Url>';
			$str .= '</item>';
		}
		$str .= '</Articles>';
		$str .= '</xml>';
		return $str;
	}

	private function setGetMessage() {
		if (!$this->post) {
			return;
		}
		$xml = simplexml_load_string($this->post);
		$this->parseXml($xml, $this->params);
	}

	private function parseXml($xml, &$xmlArray, $isFirst = false) {
		foreach ($xml->children() as $key => $value) {
			if ($value->children() && count($value) > 0) {
				if (isset($xmlArray[$key])) {
					if (!$isFirst) {
						$isFirst = true;
						$temp = $xmlArray[$key];
						$xmlArray[$key] = array();
						$xmlArray[$key][] = $temp;
						parseXml($value, $xmlArray[$key][], $isFirst);
					} else {
						parseXml($value, $xmlArray[$key][], $isFirst);
					}
				} else {
					$xmlArray[$key] = array();
					parseXml($value, $xmlArray[$key], $isFirst);
				}
			} else {
				if (isset($xmlArray[$key])) {
					if (count($xmlArray[$key]) < 2) {
						$temp = $xmlArray[$key];
						$xmlArray[$key] = array();
						$xmlArray[$key][] = trim($temp);
					}
					$xmlArray[$key][] = trim((string)$value);
				} else {
					$xmlArray[$key] = trim((string)$value);
				}
			}
		}
	}

	private function valid() {
		$echoStr = empty($_GET['echostr']) ? '' : $_GET['echostr'];
		if($this->checkSignature()){
			echo $echoStr;
		} else {
			//echo '验证失败';exit;
		}
	}

	private function checkSignature() {
		$signature = empty($_GET['signature']) ? '' : $_GET['signature'];
		$timestamp = empty($_GET['timestamp']) ? '' : $_GET['timestamp'];
		$nonce = empty($_GET['nonce']) ? '' : $_GET['nonce'];
		$tmpArr = array($this->token, $timestamp, $nonce);
		sort($tmpArr, SORT_STRING);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );
		if( $tmpStr == $signature ){
			return true;
		}else{
			return false;
		}
	}

	private function log($content) {
		file_put_contents('/tmp/weixin.test', var_export($this->params, true) . PHP_EOL, FILE_APPEND);
	}
}